package com.micro.ai.auth.controller;

import com.micro.ai.auth.dto.CaptchaVO;
import com.micro.ai.auth.dto.LoginRequest;
import com.micro.ai.auth.dto.PhoneLoginRequest;
import com.micro.ai.auth.dto.TokenResponse;
import com.micro.ai.auth.service.AuthService;
import com.micro.ai.auth.service.CaptchaService;
import com.micro.ai.auth.service.SmsService;
import com.micro.ai.auth.annotation.AuditLogAnnotation;
import com.micro.ai.commons.domain.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * 认证控制器
 * 
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@RestController
@RequestMapping("/api/auth")
@Tag(name = "认证授权", description = "用户登录、登出、令牌刷新、验证码等操作")
public class AuthController {

    @Autowired
    private AuthService authService;

    @Autowired
    private CaptchaService captchaService;

    @Autowired
    private SmsService smsService;

    /**
     * 用户登录
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "使用用户名密码登录系统，返回JWT令牌")
    @AuditLogAnnotation(action = "LOGIN", resourceType = "AUTH", description = "用户登录")
    @ApiResponses({
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "登录成功",
            content = @Content(schema = @Schema(implementation = TokenResponse.class))),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "参数错误或验证码错误"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户名或密码错误"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "403", description = "账户已锁定或已禁用")
    })
    public ApiResponse<TokenResponse> login(@Valid @RequestBody LoginRequest request, HttpServletRequest httpRequest) {
        log.info("用户登录: tenantId={}, username={}, ip={}", 
            request.getTenantId(), request.getUsername(), getClientIp(httpRequest));
        
        // 获取请求信息
        String ipAddress = getClientIp(httpRequest);
        String userAgent = httpRequest.getHeader("User-Agent");
        
        TokenResponse response = authService.login(request, ipAddress, userAgent);
        
        return ApiResponse.success("登录成功", response);
    }

    /**
     * 手机号登录
     */
    @PostMapping("/phone-login")
    @Operation(summary = "手机号登录", description = "使用手机号和短信验证码登录系统，返回JWT令牌")
    @AuditLogAnnotation(action = "LOGIN", resourceType = "AUTH", description = "手机号登录")
    @ApiResponses({
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "登录成功",
            content = @Content(schema = @Schema(implementation = TokenResponse.class))),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "参数错误或验证码错误"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "手机号未注册或验证码错误"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "403", description = "账户已锁定或已禁用")
    })
    public ApiResponse<TokenResponse> phoneLogin(@Valid @RequestBody PhoneLoginRequest request, HttpServletRequest httpRequest) {
        log.info("手机号登录: tenantId={}, phone={}, ip={}", 
            request.getTenantId(), request.getPhone(), getClientIp(httpRequest));
        
        // 获取请求信息
        String ipAddress = getClientIp(httpRequest);
        String userAgent = httpRequest.getHeader("User-Agent");
        
        TokenResponse response = authService.phoneLogin(request, ipAddress, userAgent);
        
        return ApiResponse.success("登录成功", response);
    }

    /**
     * 用户登出
     */
    @PostMapping("/logout")
    @Operation(summary = "用户登出", description = "退出登录并将令牌加入黑名单")
    @AuditLogAnnotation(action = "LOGOUT", resourceType = "AUTH", description = "用户登出")
    @ApiResponses({
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "登出成功"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "令牌格式错误"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "令牌无效或已过期")
    })
    public ApiResponse<Void> logout(
            @Parameter(description = "JWT令牌", required = true, example = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
            @RequestHeader("Authorization") String authorization) {
        // 提取token（去掉"Bearer "前缀）
        String token = authorization.substring(7);
        
        log.info("用户登出: token={}", token.substring(0, 20) + "...");
        
        authService.logout(token);
        
        return ApiResponse.successVoid("登出成功");
    }

    /**
     * 刷新令牌
     */
    @PostMapping("/refresh")
    @Operation(summary = "刷新令牌", description = "使用RefreshToken刷新AccessToken")
    @ApiResponses({
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "刷新成功",
            content = @Content(schema = @Schema(implementation = TokenResponse.class))),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "刷新令牌格式错误"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "刷新令牌无效或已过期")
    })
    public ApiResponse<TokenResponse> refresh(
            @Parameter(description = "刷新令牌", required = true) @RequestParam("refreshToken") String refreshToken) {
        log.info("刷新令牌");
        
        TokenResponse response = authService.refreshToken(refreshToken);
        
        return ApiResponse.success("令牌刷新成功", response);
    }

    /**
     * 验证令牌
     */
    @GetMapping("/validate")
    @Operation(summary = "验证令牌", description = "验证JWT令牌是否有效")
    @ApiResponses({
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "验证完成"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "令牌格式错误")
    })
    public ApiResponse<Boolean> validate(
            @Parameter(description = "JWT令牌", required = true) @RequestHeader("Authorization") String authorization) {
        // 提取token
        String token = authorization.substring(7);
        
        boolean valid = authService.validateToken(token);
        
        return ApiResponse.success("验证成功", valid);
    }

    /**
     * 获取验证码
     */
    @GetMapping("/captcha")
    @Operation(summary = "获取验证码", description = "生成图形验证码")
    @ApiResponses({
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "生成成功",
            content = @Content(schema = @Schema(implementation = CaptchaVO.class)))
    })
    public ApiResponse<CaptchaVO> captcha() {
        log.info("获取验证码");
        
        CaptchaVO captcha = captchaService.generateCaptcha();
        
        return ApiResponse.success("验证码生成成功", captcha);
    }

    /**
     * 发送短信验证码
     */
    @PostMapping("/sms-code")
    @Operation(summary = "发送短信验证码", description = "发送登录或重置密码的短信验证码")
    @ApiResponses({
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "发送成功"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "手机号格式错误"),
        @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "429", description = "发送过于频繁")
    })
    public ApiResponse<Void> smsCode(
            @Parameter(description = "手机号", required = true, example = "13800138000") @RequestParam("phone") String phone) {
        log.info("发送短信验证码: phone={}", phone);
        
        // 检查发送频率
        if (!smsService.canSendSms(phone)) {
            throw new RuntimeException("发送过于频繁，请稍后再试");
        }
        
        // 生成验证码
        String code = smsService.generateSmsCode();
        
        // 发送短信
        boolean success = smsService.sendSmsCode(phone, code);
        
        if (success) {
            return ApiResponse.successVoid("验证码已发送");
        } else {
            throw new RuntimeException("验证码发送失败，请稍后再试");
        }
    }
    
    /**
     * 获取客户端真实IP地址
     * 支持通过代理、负载均衡器后的真实IP获取
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个IP值，第一个为真实IP
            int index = ip.indexOf(',');
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        
        ip = request.getHeader("X-Real-IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        
        ip = request.getHeader("Proxy-Client-IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        
        ip = request.getHeader("WL-Proxy-Client-IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        
        ip = request.getHeader("HTTP_CLIENT_IP");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        
        ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
            return ip;
        }
        
        return request.getRemoteAddr();
    }
}

